package tech.yunland.shop.domain.service;

import com.moyuer.bsf.common.PinYinUtil;
import com.moyuer.bsf.domain.model.Attachment;
import com.moyuer.bsf.domain.model.HqlArgs;
import com.moyuer.bsf.domain.model.Organ;
import com.moyuer.bsf.domain.service.AttachmentService;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.yunland.shop.domain.dao.GoodsDao;
import tech.yunland.shop.domain.dao.GoodsPaidDao;
import tech.yunland.shop.domain.dao.GoodsPicturesDao;
import tech.yunland.shop.domain.dao.TagDao;
import tech.yunland.shop.domain.dao.TagGoodsDao;
import tech.yunland.shop.domain.model.Goods;
import tech.yunland.shop.domain.model.GoodsPictures;
import tech.yunland.shop.domain.model.Tag;
import tech.yunland.shop.domain.model.TagGoods;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 商品服务类
 *
 * @author: 袁首京<yuanshoujing@gmail.com> 16/3/29
 */
@Service
public class GoodsService {
    private final Logger logger = LoggerFactory.getLogger(getClass());

    // private static final String DELETE_ENTRIES_HQL =
    // "delete from TagGoods tg where tg.id=?";
    private static final String DELETE_ENTRIES_HQL_TAG_GOODS = "delete from TagGoods tg where tg.goods.id=?";
    // private static final String DELETE_PICTURES_HQL =
    // "delete from GoodsPictures gp where gp.goods.id=?";

    @Autowired
    private GoodsDao goodsDao;

    @Autowired
    private TagGoodsDao tagGoodsDao;

    @Autowired
    private TagDao tagDao;

    @Autowired
    private GoodsPicturesDao goodsPicturesDao;

    @Autowired
    private AttachmentService attachmentService;

    @Autowired
    private GoodsPaidDao goodsPaidDao;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    /**
     * 保存商品信息
     *
     * @param goods
     * @Return void
     */
    public void saveOrUpdate(Goods goods) {

        if (Goods.DJQ_ID.equals(goods.getId()) || Goods.JF_ID.equals(goods.getId())) {
            throw new RuntimeException("系统内置商品不允许编辑");
        }

		/*
         * ***新增 goods 判断商品编码或名称是否重复*** 
         * 1.新增 goods 没有关联 tag 
         * 2.新增 goods 关联已有 tag
		 * ***tag 只有新增 没修改*** 
		 * 3.修改 goods 关联 tag 
		 * 4.已有 goods 新增 tag 并关联 
		 * 5.已有 goods关联已有 tag 错误:xxxxx
		 * 6.已有 goods 修改 tag 并关联xxxxx
		 */

        // 1

        Goods oldGoods = goodsDao.get(goods.getId());
        goodsDao.clear();
        // 校验新增商品名称及编码
        if (oldGoods == null) {
            Goods goodsName = goodsDao.getGoodsName(goods.getName(), goods.getOrganId());
            if (goodsName != null && goodsName.getState() != -1) {
                throw new RuntimeException("商品保存失败：名称已经存在");
            } else {
                goodsDao.save(goods);
            }
        } else {
            // 校验更新商品名称
            if (oldGoods.getName().equals(goods.getName())) {
            } else {
                Goods goodsName = goodsDao.getGoodsName(goods.getName(), goods.getOrganId());
                if (goodsName != null && goodsName.getState() != -1) {
                    throw new RuntimeException("商品更新失败：名称已经存在");
                }
            }
            goodsDao.saveOrUpdate(goods);
        }

        // 保存商品图片
        if (goods.getPictureId() != null) {
            // 清理旧图片
//            goodsPicturesDao.bulkUpdate(DELETE_PICTURES_HQL, goods.getId());
            String sql = " delete from goods_pictures where goods_id = '" + goods.getId() + "'  ";
            jdbcTemplate.execute(sql);
            GoodsPictures Gp = new GoodsPictures();
            Attachment picture = attachmentService.get(goods.getPictureId());
            if (picture != null) {
                Gp.setGoods(goods);
                Gp.setPicture(picture);
                goodsPicturesDao.save(Gp);
            }
        }

        // 2
        String tagName = StringUtils.trimToEmpty(goods.getTagNames());
        if (tagName == null || tagName == "") {
            return;
        }
        tagGoodsDao.bulkUpdate(DELETE_ENTRIES_HQL_TAG_GOODS, goods.getId());
        String sql = " delete from tag_goods where goods_id =  '" + goods.getId() + " '  ";
        jdbcTemplate.execute(sql);

        String[] arrayOfString = StringUtils.split(tagName, ",");
        for (int i = 0; i < arrayOfString.length; i++) {
            String tagName1 = arrayOfString[i];

            TagGoods tagGoods = new TagGoods();
            tagGoods.setGoods(goods);

            String name = StringUtils.trimToEmpty(tagName1);
            String organId = goods.getOrganId();

            Tag jsonTag = new Tag();
            if (tagDao.sameName(name, organId) != null) {// Tag 表中存在该 tag 赋值给
                // jsonTag
                jsonTag = tagDao.sameName(name, organId);
            }
            if (tagDao.sameName(name, organId) == null) {// 不存在 tag 新增一个 tag 到
                // tag 表中 并赋值给
                // jsonTag
                jsonTag.setName(name);
                jsonTag.setSpell(PinYinUtil.getFirstSpell(jsonTag.getName()));
                jsonTag.setOrgan(goods.getOrgan());
                tagDao.save(jsonTag);

                jsonTag = tagDao.sameName(name, organId);
            }
            // 清理旧分录
            if (tagGoodsDao.getTGID(jsonTag, goods) != null) {
//                tagGoodsDao.bulkUpdate(DELETE_ENTRIES_HQL, tagGoodsDao.getTGID(jsonTag, goods).getId());
                String sql1 = "delete from tag_goods tg where tg.id = '" + tagGoodsDao.getTGID(jsonTag, goods).getId() + "' ";
                jdbcTemplate.execute(sql1);
            }
            // 关联 jsonTag 与 goods
            tagGoods.setTag(jsonTag);

            tagGoodsDao.save(tagGoods);
        }

    }

    /**
     * 标记删除商品
     *
     * @param id
     * @Return void
     */
    @Transactional
    public void delete(String id) {
        Goods goods = goodsDao.get(id);
        String useGoods = goodsPaidDao.useGoods(goods.getOrganId(), goods.getId());
        if (goods.getState() == -1) {
            return;
        } else if (Goods.DJQ_ID.equals(id) || Goods.JF_ID.equals(id)) {
            throw new RuntimeException("系统内置商品不允许删除");
        } else if (useGoods.equals("false")) {
            throw new RuntimeException("这个商品还有顾客未使用完毕，不能删除！");
        }

        goods.setState(-1);
        goodsDao.update(goods);

        // 清理商品标签
        String hql = "delete from TagGoods tg where tg.goods.id=?";
        tagGoodsDao.bulkUpdate(hql, id);
    }

    /**
     * 读取商品
     *
     * @param id
     * @Return goods
     */
    public Goods get(String id) {
        return goodsDao.get(id);
    }

    /**
     * 更新权重
     *
     * @param id
     */
    public void updateRate(String id) {
        Goods goods = goodsDao.get(id);
        if (goods == null) {
            return;
        }

        Long rate = goods.getRate();
        if (rate == null) {
            rate = 1l;
        } else if (rate < Long.MAX_VALUE) {
            rate += 1l;
        } else {
            rate = Long.MAX_VALUE;
        }

        goods.setRate(rate);

        goodsDao.update(goods);
    }

    /**
     * 查找指定机构下某名称的商品
     *
     * @param name
     * @param organId
     * @return
     */
    public List<Goods> getList(String name, String organId) {
        name = StringUtils.trimToNull(name);
        organId = StringUtils.trimToNull(organId);

        if (name == null && organId == null) {
            return null;
        }

        DetachedCriteria criteria = DetachedCriteria.forClass(Goods.class);
        if (name != null) {
            criteria.add(Restrictions.eq("name", name));
        }

        if (organId != null) {
            criteria.createCriteria("organ").add(Restrictions.idEq(organId));
        }

        criteria.addOrder(Order.desc("createTime"));

        return goodsDao.findByCriteria(criteria);
    }

    /**
     * 读取系统内置商品
     *
     * @return
     */
    public List<Goods> getSystemGoods() {
        DetachedCriteria criteria = DetachedCriteria.forClass(Goods.class);
        criteria.add(Restrictions.eq("kindCode", "0"));
        criteria.add(Restrictions.eq("state", 1));
        criteria.createCriteria("organ").add(Restrictions.idEq(Organ.ROOT_ID));

        List<Goods> result = goodsDao.findByCriteria(criteria);
        return result;
    }

    /**
     * 根据条件生成 hql 查询
     *
     * @param param
     * @param states
     * @param tags
     * @param organIds
     * @param withBuildin 是否包含系统内置商品
     * @param kindCodes
     * @return
     */
    private HqlArgs genHqlArgs(String param, List<Integer> states, List<String> tags, List<String> organIds,
                               boolean withBuildin, List<Integer> kindCodes) {
        param = StringUtils.trimToEmpty(param);

        Map<String, Object> args = new HashMap<String, Object>();

        String hql = "from Goods g where 1=1";
        if (tags != null && tags.size() > 0) {
            hql += " and exists (from TagGoods tg where tg.goods.id=g.id and tg.tag.name";
            if (tags.size() == 1) {
                hql += " = :tags)";
                args.put("tags", tags.get(0));
            } else {
                hql += " in :tags)";
                args.put("tags", tags);
            }
        }


        if (StringUtils.isNotBlank(param)) {
            hql += " and (g.code like :arg or g.name like :arg or g.spell like :arg or g.remark like :arg)";
            args.put("arg", "%" + param + "%");
        }

        if (organIds != null && organIds.size() > 0) {
            if (organIds.size() == 1) {
                hql += " and g.organ.id = :organId";
                args.put("organId", organIds.get(0));
            } else {
                hql += " and g.organ.id in :organIds";
                args.put("organIds", organIds);
            }
        }

        if (kindCodes != null && kindCodes.size() > 0) {
            if (kindCodes.size() == 1) {
                hql += " and g.kindCode = :kindCode";
                args.put("kindCode", kindCodes.get(0));
            } else {
                hql += " and g.kindCode in :kindCodes";
                args.put("kindCodes", kindCodes);
            }
        }

        if (states != null && states.size() > 0) {
            if (states.size() == 1) {
                hql += " and g.state=:states";
                args.put("states", states.get(0));
            } else {
                hql += " and g.state in :states";
                args.put("states", states);
            }
        }

        if (withBuildin) {
            hql += " or (g.kindCode = '0' and g.state = 1 and g.organ.id = :rootOrganId)";
            args.put("rootOrganId", Organ.ROOT_ID);
        }

        return new HqlArgs(hql, args);
    }

    /**
     * 根据条件生成 hql 语句 TagGoods
     *
     * @param goodsId
     * @param tagId
     * @return
     */
    private HqlArgs genHqlArgsTG(String goodsId, String tagId) {

        Map<String, Object> args = new HashMap<String, Object>();

        String hql = "from TagGoods tg where 1=1";
        if (goodsId != null) {
            hql += " and tg.goodsId = goodsId";
            args.put("goodsId", goodsId);
        }

        if (tagId != null) {
            hql += "and tg.tagId = tagId";
            args.put("tagId", tagId);
        }

        return new HqlArgs(hql, args);
    }

    /**
     * 根据入参查询结果数量
     *
     * @param param
     * @param states
     * @param tags
     * @param organIds
     * @param kindCodes
     * @return
     */
    public int getResultSize(String param, List<Integer> states, List<String> tags, List<String> organIds,
                             boolean withBuildin, List<Integer> kindCodes) {
        HqlArgs hqlArgs = genHqlArgs(param, states, tags, organIds, withBuildin, kindCodes);
        return (int) goodsDao.getCount(hqlArgs.getHql(), hqlArgs.getArgs());
    }

    /**
     * 根据入参查询结果数量 TagGoods
     *
     * @param goodsId
     * @param tagId
     * @return
     */
    public int getResultSizeTG(String goodsId, String tagId) {
        HqlArgs hqlArgs = genHqlArgsTG(goodsId, tagId);
        return tagGoodsDao.findByNamedParam(hqlArgs.getHql(), hqlArgs.getArgs()).size();
    }

    /**
     * 根据入参查询结果集 Goods
     *
     * @param param
     * @param states
     * @param tags
     * @param startIndex 起始索引
     * @param length     数量
     * @param organIds
     * @param kindCodes
     * @return
     * @Return List<goods>
     */
    public List<Goods> getResultInfos(String param, List<Integer> states, List<String> tags, Integer startIndex,
                                      Integer length, List<String> organIds, boolean withBuildin, List<Integer> kindCodes) {
        HqlArgs hqlArgs = genHqlArgs(param, states, tags, organIds, withBuildin, kindCodes);
        String hql = "select g " + hqlArgs.getHql() + " order by g.createTime DESC, g.state desc ,g.rate desc";

        return goodsDao.findByNamedParam(hql, startIndex, length, hqlArgs.getArgs());
    }

    /**
     * 根据入参查询结果集 TagGoods
     *
     * @param goodsId
     * @param tagId
     * @param startIndex
     * @param length
     * @return
     */
    public List<TagGoods> getResultInfoTG(String goodsId, String tagId, Integer startIndex, Integer length) {
        HqlArgs hqlArgs = genHqlArgsTG(goodsId, tagId);
        String hql = "select tg " + hqlArgs.getHql();

        return tagGoodsDao.findByNamedParam(hql, startIndex, length, hqlArgs.getArgs());
    }
}
